'''
Given a link to an article retrieve its reference and citation list
'''
from threading import Thread
#from BeautifulSoup import BeautifulSoup
import mechanize
import re
import common_tools
import datetime
import time
from Bio import Entrez, Medline
from PyQt4 import QtCore, QtGui, Qt

def timer_stop(timer_st):
    time_end = datetime.datetime.now()
    elapsed_time = time_end - timer_st
    print "Elapsed time = %s" % elapsed_time.seconds
    
class RefCiteRetrieval():
    def __init__ (self, pmid, titlemsg, config_dict, parent=None):
        #QtGui.QWidget.__init__(self, parent)
        self.pmid = pmid
        self.titlemsg = titlemsg
        self.config_dict = config_dict
        self.all_citations_done = False
        self.done_citations = 0
        Entrez.email = 'a.varier@gmail.com'

    def get_related(self):
        details_titles = ['PMRecord', 'Title', 'ArticleLink',
                          'Authors', 'Journal', 'Issue', 'Pages', 'Year', 'EID']
        try:
            records = Entrez.read(Entrez.elink(dbfrom="pubmed", db="pubmed",
                                       LinkName="pubmed_pubmed",
                                       from_uid=self.pmid))
            pmc_ids = [link["Id"] for link in records[0]["LinkSetDb"][0]["Link"]]
            handle = Entrez.efetch(db="pubmed", id=pmc_ids, rettype="medline", retmode="text")
            records = Medline.parse(handle)
            records = list(records)
            details = self.convert_records_to_output_array(records)
            if len(records) == 0:
                raise
        except:
            msg = "No related articles found for PMID %s" % self.pmid
            x = {}
            for i in details_titles:
                x[i] = ''
            x['Title'] = msg
            return [x]
        return details
    
    def get_references(self):
        details_titles = ['PMRecord', 'Title', 'ArticleLink',
                          'Authors', 'Journal', 'Issue', 'Pages', 'Year', 'EID']
        try:
            records = Entrez.read(Entrez.elink(dbfrom="pubmed", db="pubmed",
                                   LinkName="pubmed_pubmed_refs",
                                   from_uid=self.pmid))
            pubmed_ids = [link["Id"] for link in records[0]["LinkSetDb"][0]["Link"]]
            handle = Entrez.efetch(db="pubmed", id=pubmed_ids, rettype="medline", retmode="text")
            records = Medline.parse(handle)
            records = list(records)
            details = self.convert_records_to_output_array(records)
            if len(records) == 0:
                raise
        except:
            msg = "No references found for PMID %s" % self.pmid
            x = {}
            for i in details_titles:
                x[i] = ''
            x['Title'] = msg
            return [x]
        return details            

    def get_citations(self):
        details_titles = ['PMRecord', 'Title', 'ArticleLink',
                          'Authors', 'Journal', 'Issue', 'Pages', 'Year', 'EID']
        try:
            records = Entrez.read(Entrez.elink(dbfrom="pubmed", db="pmc",
                                   LinkName="pubmed_pmc_refs",
                                   from_uid=self.pmid))
            pmc_ids = [link["Id"] for link in records[0]["LinkSetDb"][0]["Link"]]
            results2 = Entrez.read(Entrez.elink(dbfrom="pmc", db="pubmed", LinkName="pmc_pubmed",
                                                from_uid=",".join(pmc_ids)))
            pubmed_ids = [link["Id"] for link in results2[0]["LinkSetDb"][0]["Link"]]
            handle = Entrez.efetch(db="pubmed", id=pubmed_ids, rettype="medline", retmode="text")
            records = Medline.parse(handle)
            records = list(records)
            details = self.convert_records_to_output_array(records)
            if len(records) == 0:
                raise
        except:
            msg = "No citations found for PMID %s" % self.pmid
            x = {}
            for i in details_titles:
                x[i] = ''
            x['Title'] = msg
            return [x]
        return details

    def convert_records_to_output_array(self, records):
        details = []
        for record in records:
            tempRecord = {}
            tempRecord['Title'] = record.get("TI")
            tempRecord['PMRecord'] = record.get("PMID")

            if record.get('AU'):
                tempRecord['Authors'] = ", ".join(record.get('AU'))
            else:
                tempRecord['Authors'] = ''
            if record.get("JT"):
                tempRecord['Journal'] = record.get("JT")
            elif record.get("CTI"):
                tempRecord['Journal'] = ''.join(record["CTI"])
            else:
                tempRecord['Journal'] = ''
            issue = record.get('VI') if record.get('VI') else ''
            issue = '%s (%s)' % (issue, record.get('IP')) if record.get('IP') else issue
            pages = record.get('PG') if record.get('PG') else ''
            pages = record.get('IS') if pages == '' else pages
            tempRecord['Pages'] = pages
            tempRecord['Issue'] = issue
            tempRecord['Year'] = record.get('DA')[:4]
            tempRecord['ArticleRecord'] = ''
            pmc_val = record.get('PMC')
            print pmc_val
            tempRecord['ArticleLink'] = ''
            tempRecord['EID'] = tempRecord['PMRecord']
            details += [tempRecord]
        return details
                
if __name__ == '__main__':
    timer_st = datetime.datetime.now()
    scopus_article_url = 'http://www.scopus.com/record/display.url?eid=2-s2.0-38449112143&origin=resultslist&sort=plf-f&src=s&sid=UXdSquxE0c3c7I8-NBb42_-:70&sot=q&sdt=b&sl=33&s=TITLE-ABS-KEY-AUTH(poo+mm+review)&relpos=5&relpos=5'
    rcr = RefCiteRetrieval(scopus_article_url, 'references')
    ref_details = rcr.get_references()
    f = open('Misc/ref_details', 'w'); f.write(str(ref_details)); f.close()
    cite_details = rcr.get_citations()
    f = open('Misc/cite_details', 'w'); f.write(str(cite_details)); f.close()
    #rcr.get_citations()
    print 'References:', len(ref_details), 'Citations:', len(cite_details)
    timer_stop(timer_st)
